[Fix] Revert UI - Organization Usage (#16980)

* Revert "[Feature] UI - Organization Usage in Usage Tab (#16614)"

This reverts commit 4de182c98f.

* Networking Changes
This commit is contained in:
yuneng-jiang
2025-11-22 16:02:12 -08:00
committed by GitHub
parent de897ce389
commit 5da77ac40a
13 changed files with 143 additions and 290 deletions
@@ -15,7 +15,6 @@ const UsagePage = () => {
userID={userId}
teams={teams ?? []}
premiumUser={premiumUser}
organizations={[]}
/>
);
};
-1
View File
@@ -480,7 +480,6 @@ export default function CreateKeyPage() {
userRole={userRole}
accessToken={accessToken}
teams={(teams as Team[]) ?? []}
organizations={(organizations as Organization[]) ?? []}
premiumUser={premiumUser}
/>
) : (
@@ -22,7 +22,7 @@ const EntityUsageExportModal: React.FC<EntityUsageExportModalProps> = ({
const [exportScope, setExportScope] = useState<ExportScope>("daily");
const [isExporting, setIsExporting] = useState(false);
const entityLabel = entityType.charAt(0).toUpperCase() + entityType.slice(1);
const entityLabel = entityType === "tag" ? "Tag" : "Team";
const modalTitle = customTitle || `Export ${entityLabel} Usage`;
const handleExportCSV = () => {
@@ -5,7 +5,7 @@ import type { ExportScope } from "./types";
interface ExportTypeSelectorProps {
value: ExportScope;
onChange: (value: ExportScope) => void;
entityType: "tag" | "team" | "organization";
entityType: "tag" | "team";
}
const ExportTypeSelector: React.FC<ExportTypeSelectorProps> = ({ value, onChange, entityType }) => {
@@ -36,3 +36,4 @@ const ExportTypeSelector: React.FC<ExportTypeSelectorProps> = ({ value, onChange
};
export default ExportTypeSelector;
@@ -7,7 +7,7 @@ import type { EntitySpendData } from "./types";
interface UsageExportHeaderProps {
dateValue: DateRangePickerValue;
entityType: "tag" | "team" | "organization";
entityType: "tag" | "team";
spendData: EntitySpendData;
// Optional filter props
showFilters?: boolean;
@@ -17,7 +17,7 @@ export interface EntitySpendData {
export interface EntityUsageExportModalProps {
isOpen: boolean;
onClose: () => void;
entityType: "tag" | "team" | "organization";
entityType: "tag" | "team";
spendData: EntitySpendData;
dateRange: DateRangePickerValue;
selectedFilters: string[];
@@ -59,3 +59,4 @@ export interface EntityBreakdown {
id: string;
};
}
@@ -50,7 +50,7 @@ export const generateDailyData = (spendData: EntitySpendData, entityLabel: strin
[entityLabel]: data.metadata?.team_alias || entity,
[`${entityLabel} ID`]: entity,
"Spend ($)": formatNumberWithCommas(data.metrics.spend, 4),
Requests: data.metrics.api_requests,
"Requests": data.metrics.api_requests,
"Successful Requests": data.metrics.successful_requests,
"Failed Requests": data.metrics.failed_requests,
"Total Tokens": data.metrics.total_tokens,
@@ -109,9 +109,9 @@ export const generateDailyWithModelsData = (spendData: EntitySpendData, entityLa
[`${entityLabel} ID`]: entity,
Model: model,
"Spend ($)": formatNumberWithCommas(metrics.spend, 4),
Requests: metrics.requests,
Successful: metrics.successful,
Failed: metrics.failed,
"Requests": metrics.requests,
"Successful": metrics.successful,
"Failed": metrics.failed,
"Total Tokens": metrics.tokens,
});
});
@@ -137,7 +137,7 @@ export const generateExportData = (
};
export const generateMetadata = (
entityType: "tag" | "team" | "organization",
entityType: "tag" | "team",
dateRange: { from?: Date; to?: Date },
selectedFilters: string[],
exportScope: ExportScope,
@@ -159,3 +159,4 @@ export const generateMetadata = (
total_tokens: spendData.metadata.total_tokens,
},
});
@@ -1,6 +1,6 @@
import { Organization } from "../networking";
export const defaultOrg = {
organization_id: "default_organization",
organization_id: null,
organization_alias: "Default Organization",
} as Organization;
@@ -3,6 +3,7 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import EntityUsage from "./entity_usage";
import * as networking from "./networking";
// Polyfill ResizeObserver for test environment
beforeAll(() => {
if (typeof window !== "undefined" && !window.ResizeObserver) {
window.ResizeObserver = class ResizeObserver {
@@ -17,7 +18,6 @@ beforeAll(() => {
vi.mock("./networking", () => ({
tagDailyActivityCall: vi.fn(),
teamDailyActivityCall: vi.fn(),
organizationDailyActivityCall: vi.fn(),
}));
// Mock the child components to simplify testing
@@ -41,7 +41,6 @@ vi.mock("./EntityUsageExport", () => ({
describe("EntityUsage", () => {
const mockTagDailyActivityCall = vi.mocked(networking.tagDailyActivityCall);
const mockTeamDailyActivityCall = vi.mocked(networking.teamDailyActivityCall);
const mockOrganizationDailyActivityCall = vi.mocked(networking.organizationDailyActivityCall);
const mockSpendData = {
results: [
@@ -127,10 +126,8 @@ describe("EntityUsage", () => {
beforeEach(() => {
mockTagDailyActivityCall.mockClear();
mockTeamDailyActivityCall.mockClear();
mockOrganizationDailyActivityCall.mockClear();
mockTagDailyActivityCall.mockResolvedValue(mockSpendData);
mockTeamDailyActivityCall.mockResolvedValue(mockSpendData);
mockOrganizationDailyActivityCall.mockResolvedValue(mockSpendData);
});
it("should render with tag entity type and display spend metrics", async () => {
@@ -167,21 +164,6 @@ describe("EntityUsage", () => {
});
});
it("should render with organization entity type and call organization API", async () => {
const { getByText, getAllByText } = render(<EntityUsage {...defaultProps} entityType="organization" />);
await waitFor(() => {
expect(mockOrganizationDailyActivityCall).toHaveBeenCalled();
});
expect(getByText("Organization Spend Overview")).toBeInTheDocument();
await waitFor(() => {
const spendElements = getAllByText("$100.50");
expect(spendElements.length).toBeGreaterThan(0);
});
});
it("should switch between tabs", async () => {
render(<EntityUsage {...defaultProps} />);
@@ -23,7 +23,7 @@ import {
} from "@tremor/react";
import { ActivityMetrics, processActivityData } from "./activity_metrics";
import { DailyData, BreakdownMetrics, KeyMetricWithMetadata, EntityMetricWithMetadata, TagUsage } from "./usage/types";
import { organizationDailyActivityCall, tagDailyActivityCall, teamDailyActivityCall } from "./networking";
import { tagDailyActivityCall, teamDailyActivityCall } from "./networking";
import TopKeyView from "./top_key_view";
import { formatNumberWithCommas } from "@/utils/dataUtils";
import { valueFormatterSpend } from "./usage/utils/value_formatters";
@@ -68,7 +68,7 @@ export interface EntityList {
interface EntityUsageProps {
accessToken: string | null;
entityType: "tag" | "team" | "organization";
entityType: "tag" | "team";
entityId?: string | null;
userID: string | null;
userRole: string | null;
@@ -126,15 +126,6 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
selectedTags.length > 0 ? selectedTags : null,
);
setSpendData(data);
} else if (entityType === "organization") {
const data = await organizationDailyActivityCall(
accessToken,
startTime,
endTime,
1,
selectedTags.length > 0 ? selectedTags : null,
);
setSpendData(data);
} else {
throw new Error("Invalid entity type");
}
@@ -334,16 +325,6 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
}));
};
const getFilterLabel = (entityType: string) => {
return `Filter by ${entityType}`;
};
const getFilterPlaceholder = (entityType: string) => {
return `Select ${entityType} to filter...`;
};
const capitalizedEntityLabel = entityType.charAt(0).toUpperCase() + entityType.slice(1);
return (
<div style={{ width: "100%" }} className="relative">
<UsageExportHeader
@@ -351,8 +332,8 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
entityType={entityType}
spendData={spendData}
showFilters={entityList !== null && entityList.length > 0}
filterLabel={getFilterLabel(entityType)}
filterPlaceholder={getFilterPlaceholder(entityType)}
filterLabel={`Filter by ${entityType === "tag" ? "Tags" : "Teams"}`}
filterPlaceholder={`Select ${entityType === "tag" ? "tags" : "teams"} to filter...`}
selectedFilters={selectedTags}
onFiltersChange={setSelectedTags}
filterOptions={getAllTags() || undefined}
@@ -369,7 +350,7 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
{/* Total Spend Card */}
<Col numColSpan={2}>
<Card>
<Title>{capitalizedEntityLabel} Spend Overview</Title>
<Title>{entityType === "tag" ? "Tag" : "Team"} Spend Overview</Title>
<Grid numItems={5} className="gap-4 mt-4">
<Card>
<Title>Total Spend</Title>
@@ -432,10 +413,10 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
<p className="text-gray-600">Failed: {data.metrics.failed_requests}</p>
<p className="text-gray-600">Total Tokens: {data.metrics.total_tokens}</p>
<p className="text-gray-600">
Total {capitalizedEntityLabel}s: {entityCount}
{entityType === "tag" ? "Total Tags" : "Total Teams"}: {entityCount}
</p>
<div className="mt-2 border-t pt-2">
<p className="font-semibold">Spend by {capitalizedEntityLabel}:</p>
<p className="font-semibold">Spend by {entityType === "tag" ? "Tag" : "Team"}:</p>
{Object.entries(data.breakdown.entities || {})
.sort(([, a], [, b]) => {
const spendA = (a as EntityMetrics).metrics.spend;
@@ -468,10 +449,10 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
<Card>
<div className="flex flex-col space-y-4">
<div className="flex flex-col space-y-2">
<Title>Spend Per {capitalizedEntityLabel}</Title>
<Title>Spend Per {entityType === "tag" ? "Tag" : "Team"}</Title>
<Subtitle className="text-xs">Showing Top 5 by Spend</Subtitle>
<div className="flex items-center text-sm text-gray-500">
<span>Get Started by Tracking cost per {capitalizedEntityLabel} </span>
<span>Get Started by Tracking cost per {entityType} </span>
<a
href="https://docs.litellm.ai/docs/proxy/enterprise#spend-tracking"
className="text-blue-500 hover:text-blue-700 ml-1"
@@ -515,7 +496,7 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
<Table>
<TableHead>
<TableRow>
<TableHeaderCell>{capitalizedEntityLabel}</TableHeaderCell>
<TableHeaderCell>{entityType === "tag" ? "Tag" : "Team"}</TableHeaderCell>
<TableHeaderCell>Spend</TableHeaderCell>
<TableHeaderCell className="text-green-600">Successful</TableHeaderCell>
<TableHeaderCell className="text-red-600">Failed</TableHeaderCell>
@@ -143,7 +143,7 @@ export interface ListPromptsResponse {
}
export interface Organization {
organization_id: string;
organization_id: string | null;
organization_alias: string;
budget_id: string;
metadata: Record<string, any>;
@@ -1570,70 +1570,21 @@ export const transformRequestCall = async (accessToken: string, request: object)
}
};
type DailyActivityQueryValue = string | number | string[] | null | undefined;
const DEFAULT_DAILY_ACTIVITY_PAGE_SIZE = "1000";
const appendDailyActivityQueryParam = (params: URLSearchParams, key: string, value: DailyActivityQueryValue) => {
if (value === null || value === undefined) {
return;
}
if (Array.isArray(value)) {
if (value.length > 0) {
params.append(key, value.join(","));
}
return;
}
params.append(key, `${value}`);
};
const buildDailyActivityUrl = (
endpoint: string,
startTime: Date,
endTime: Date,
page: number,
extraQueryParams?: Record<string, DailyActivityQueryValue>,
) => {
const resolvedEndpoint = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
const baseUrl = proxyBaseUrl ? `${proxyBaseUrl}${resolvedEndpoint}` : resolvedEndpoint;
const params = new URLSearchParams();
params.append("start_date", formatDate(startTime));
params.append("end_date", formatDate(endTime));
params.append("page_size", DEFAULT_DAILY_ACTIVITY_PAGE_SIZE);
params.append("page", page.toString());
if (extraQueryParams) {
Object.entries(extraQueryParams).forEach(([key, value]) => {
appendDailyActivityQueryParam(params, key, value);
});
}
const queryString = params.toString();
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
};
type DailyActivityCallOptions = {
accessToken: string;
endpoint: string;
startTime: Date;
endTime: Date;
page?: number;
extraQueryParams?: Record<string, DailyActivityQueryValue>;
};
const fetchDailyActivity = async ({
accessToken,
endpoint,
startTime,
endTime,
page = 1,
extraQueryParams,
}: DailyActivityCallOptions) => {
export const userDailyActivityCall = async (accessToken: string, startTime: Date, endTime: Date, page: number = 1) => {
/**
* Get daily user activity on proxy
*/
try {
const url = buildDailyActivityUrl(endpoint, startTime, endTime, page, extraQueryParams);
let url = proxyBaseUrl ? `${proxyBaseUrl}/user/daily/activity` : `/user/daily/activity`;
const queryParams = new URLSearchParams();
queryParams.append("start_date", formatDate(startTime));
queryParams.append("end_date", formatDate(endTime));
queryParams.append("page_size", "1000");
queryParams.append("page", page.toString());
const queryString = queryParams.toString();
if (queryString) {
url += `?${queryString}`;
}
const response = await fetch(url, {
method: "GET",
@@ -1653,24 +1604,11 @@ const fetchDailyActivity = async ({
const data = await response.json();
return data;
} catch (error) {
console.error(`Failed to fetch daily activity (${endpoint}):`, error);
console.error("Failed to create key:", error);
throw error;
}
};
export const userDailyActivityCall = async (accessToken: string, startTime: Date, endTime: Date, page: number = 1) => {
/**
* Get daily user activity on proxy
*/
return fetchDailyActivity({
accessToken,
endpoint: "/user/daily/activity",
startTime,
endTime,
page,
});
};
export const tagDailyActivityCall = async (
accessToken: string,
startTime: Date,
@@ -1681,16 +1619,42 @@ export const tagDailyActivityCall = async (
/**
* Get daily user activity on proxy
*/
return fetchDailyActivity({
accessToken,
endpoint: "/tag/daily/activity",
startTime,
endTime,
page,
extraQueryParams: {
tags,
},
});
try {
let url = proxyBaseUrl ? `${proxyBaseUrl}/tag/daily/activity` : `/tag/daily/activity`;
const queryParams = new URLSearchParams();
queryParams.append("start_date", formatDate(startTime));
queryParams.append("end_date", formatDate(endTime));
queryParams.append("page_size", "1000");
queryParams.append("page", page.toString());
if (tags) {
queryParams.append("tags", tags.join(","));
}
const queryString = queryParams.toString();
if (queryString) {
url += `?${queryString}`;
}
const response = await fetch(url, {
method: "GET",
headers: {
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
const errorData = await response.json();
const errorMessage = deriveErrorMessage(errorData);
handleError(errorMessage);
throw new Error(errorMessage);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Failed to create key:", error);
throw error;
}
};
export const teamDailyActivityCall = async (
@@ -1703,36 +1667,43 @@ export const teamDailyActivityCall = async (
/**
* Get daily user activity on proxy
*/
return fetchDailyActivity({
accessToken,
endpoint: "/team/daily/activity",
startTime,
endTime,
page,
extraQueryParams: {
team_ids: teamIds,
exclude_team_ids: "litellm-dashboard",
},
});
};
try {
let url = proxyBaseUrl ? `${proxyBaseUrl}/team/daily/activity` : `/team/daily/activity`;
const queryParams = new URLSearchParams();
queryParams.append("start_date", formatDate(startTime));
queryParams.append("end_date", formatDate(endTime));
queryParams.append("page_size", "1000");
queryParams.append("page", page.toString());
if (teamIds) {
queryParams.append("team_ids", teamIds.join(","));
}
queryParams.append("exclude_team_ids", "litellm-dashboard");
const queryString = queryParams.toString();
if (queryString) {
url += `?${queryString}`;
}
export const organizationDailyActivityCall = async (
accessToken: string,
startTime: Date,
endTime: Date,
page: number = 1,
organizationIds: string[] | null = null,
) => {
return fetchDailyActivity({
accessToken,
endpoint: "/organization/daily/activity",
startTime,
endTime,
page,
extraQueryParams: {
organization_ids: organizationIds,
},
});
const response = await fetch(url, {
method: "GET",
headers: {
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
const errorData = await response.json();
const errorMessage = deriveErrorMessage(errorData);
handleError(errorMessage);
throw new Error(errorMessage);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Failed to create key:", error);
throw error;
}
};
export const getTotalSpendCall = async (accessToken: string) => {
@@ -1,7 +1,6 @@
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { describe, it, expect, vi, beforeEach, beforeAll } from "vitest";
import NewUsagePage from "./new_usage";
import type { Organization } from "./networking";
import * as networking from "./networking";
// Polyfill ResizeObserver for test environment
@@ -154,26 +153,6 @@ describe("NewUsage", () => {
},
};
const mockOrganizations: Organization[] = [
{
organization_id: "org-123",
organization_alias: "Acme Org",
budget_id: "budget-1",
metadata: {},
models: [],
spend: 0,
model_spend: {},
created_at: "2025-01-01T00:00:00Z",
created_by: "user-123",
updated_at: "2025-01-02T00:00:00Z",
updated_by: "user-123",
litellm_budget_table: null,
teams: null,
users: null,
members: null,
},
];
const defaultProps = {
accessToken: "test-token",
userRole: "Admin",
@@ -196,7 +175,6 @@ describe("NewUsage", () => {
members_with_roles: [],
},
],
organizations: [],
premiumUser: true,
};
@@ -272,21 +250,4 @@ describe("NewUsage", () => {
expect(entityUsageElements.length).toBeGreaterThan(0);
});
});
it("should show organization usage banner and tab for admins", async () => {
const { getByText, getAllByText } = render(<NewUsagePage {...defaultProps} organizations={mockOrganizations} />);
await waitFor(() => {
expect(mockUserDailyActivityAggregatedCall).toHaveBeenCalled();
});
const organizationTab = getByText("Organization Usage");
fireEvent.click(organizationTab);
await waitFor(() => {
expect(getByText("Organization usage is a new feature.")).toBeInTheDocument();
const entityUsageElements = getAllByText("Entity Usage");
expect(entityUsageElements.length).toBeGreaterThan(0);
});
});
});
@@ -6,66 +6,58 @@
* Works at 1m+ spend logs, by querying an aggregate table instead.
*/
import React, { useState, useEffect, useMemo, useCallback } from "react";
import {
BarChart,
Card,
Col,
DateRangePickerValue,
DonutChart,
Title,
Text,
Grid,
Tab,
Col,
TabGroup,
Table,
TableBody,
TableCell,
TableHead,
TableHeaderCell,
TableRow,
TabList,
Tab,
TabPanel,
TabPanels,
Text,
Title,
DonutChart,
Table,
TableHead,
TableRow,
TableHeaderCell,
TableBody,
TableCell,
DateRangePickerValue,
} from "@tremor/react";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Alert } from "antd";
import { formatNumberWithCommas } from "@/utils/dataUtils";
import { Button } from "@tremor/react";
import { all_admin_roles } from "../utils/roles";
import { ActivityMetrics, processActivityData } from "./activity_metrics";
import CloudZeroExportModal from "./cloudzero_export_modal";
import EntityUsage, { EntityList } from "./entity_usage";
import EntityUsageExportModal from "./EntityUsageExport";
import { Team } from "./key_team_helpers/key_list";
import { Organization, tagListCall, userDailyActivityAggregatedCall, userDailyActivityCall } from "./networking";
import { getProviderLogoAndName } from "./provider_info_helpers";
import AdvancedDatePicker from "./shared/advanced_date_picker";
import { ChartLoader } from "./shared/chart_loader";
import { userDailyActivityCall, userDailyActivityAggregatedCall, tagListCall } from "./networking";
import { Tag } from "./tag_management/types";
import TopKeyView from "./top_key_view";
import { DailyData, KeyMetricWithMetadata, MetricWithMetadata } from "./usage/types";
import { valueFormatterSpend } from "./usage/utils/value_formatters";
import UserAgentActivity from "./user_agent_activity";
import ViewUserSpend from "./view_user_spend";
import TopKeyView from "./top_key_view";
import { ActivityMetrics, processActivityData } from "./activity_metrics";
import UserAgentActivity from "./user_agent_activity";
import { DailyData, MetricWithMetadata, KeyMetricWithMetadata } from "./usage/types";
import EntityUsage from "./entity_usage";
import { all_admin_roles } from "../utils/roles";
import { Team } from "./key_team_helpers/key_list";
import { EntityList } from "./entity_usage";
import { formatNumberWithCommas } from "@/utils/dataUtils";
import { valueFormatterSpend } from "./usage/utils/value_formatters";
import CloudZeroExportModal from "./cloudzero_export_modal";
import { ChartLoader } from "./shared/chart_loader";
import { getProviderLogoAndName } from "./provider_info_helpers";
import EntityUsageExportModal from "./EntityUsageExport";
import AdvancedDatePicker from "./shared/advanced_date_picker";
import { Button } from "@tremor/react";
interface NewUsagePageProps {
accessToken: string | null;
userRole: string | null;
userID: string | null;
teams: Team[];
organizations: Organization[];
premiumUser: boolean;
}
const NewUsagePage: React.FC<NewUsagePageProps> = ({
accessToken,
userRole,
userID,
teams,
organizations,
premiumUser,
}) => {
const NewUsagePage: React.FC<NewUsagePageProps> = ({ accessToken, userRole, userID, teams, premiumUser }) => {
const [userSpendData, setUserSpendData] = useState<{
results: DailyData[];
metadata: any;
@@ -89,7 +81,6 @@ const NewUsagePage: React.FC<NewUsagePageProps> = ({
const [modelViewType, setModelViewType] = useState<"groups" | "individual">("groups");
const [isCloudZeroModalOpen, setIsCloudZeroModalOpen] = useState(false);
const [isGlobalExportModalOpen, setIsGlobalExportModalOpen] = useState(false);
const [showOrganizationBanner, setShowOrganizationBanner] = useState(true);
const getAllTags = async () => {
if (!accessToken) {
@@ -424,11 +415,6 @@ const NewUsagePage: React.FC<NewUsagePageProps> = ({
<div className="flex items-end justify-start gap-6 mb-6">
<TabList variant="solid">
{all_admin_roles.includes(userRole || "") ? <Tab>Global Usage</Tab> : <Tab>Your Usage</Tab>}
{all_admin_roles.includes(userRole || "") ? (
<Tab>Organization Usage</Tab>
) : (
<Tab>Your Organization Usage</Tab>
)}
<Tab>Team Usage</Tab>
{all_admin_roles.includes(userRole || "") ? <Tab>Tag Usage</Tab> : <></>}
{all_admin_roles.includes(userRole || "") ? <Tab>User Agent Activity</Tab> : <></>}
@@ -751,35 +737,6 @@ const NewUsagePage: React.FC<NewUsagePageProps> = ({
</TabGroup>
</TabPanel>
{/* Organization Usage Panel */}
<TabPanel>
{showOrganizationBanner && (
<Alert
banner
type="info"
message="Organization usage is a new feature."
description="Spend is tracked from feature launch and previous data isn't backfilled, so only future usage appears here."
closable
onClose={() => setShowOrganizationBanner(false)}
className="mb-5"
/>
)}
<EntityUsage
accessToken={accessToken}
entityType="organization"
userID={userID}
userRole={userRole}
dateValue={dateValue}
entityList={
organizations?.map((organization) => ({
label: organization.organization_alias,
value: organization.organization_id,
})) || null
}
premiumUser={premiumUser}
/>
</TabPanel>
{/* Team Usage Panel */}
<TabPanel>
<EntityUsage