mirror of
https://github.com/coder/coder.git
synced 2026-11-02 13:33:30 +08:00
feat(site): polish AI budget members table (#26805)
Finishing touches for the AI cost control group members table.
- Spend stays primary-colored until near the budget limit, via a new
AIBudgetAmount component
- "AI budget period" label shows the current spend window in local
time, next to the members tab
- Budget tooltip notes the reset date and the group's default limit
- "Budget type" renamed to "Budget group", with a badge for the
governing group or override
- Distinguishes $0 budget ("None") from no budget ("Unlimited")
- Unattributed spend from another group shows a note instead of a dash
- "Manage AI budget" disabled only when another named group governs
- Replaces UserAISpend with generated UserAISpendStatus, fixing
limit_source
Closes #26401
This commit is contained in:
+3
-12
@@ -213,7 +213,7 @@ export type GroupMemberAICostControl = Readonly<{
|
||||
current_spend_micros: number;
|
||||
spend_limit_micros: number | null;
|
||||
effective_group_id: string | null;
|
||||
limit_source: "group" | "override" | null;
|
||||
limit_source: TypesGen.AIBudgetLimitSource | null;
|
||||
}>;
|
||||
export type GroupMemberWithAICostControl = TypesGen.ReducedUser &
|
||||
Readonly<{ ai_cost_control?: GroupMemberAICostControl }>;
|
||||
@@ -223,15 +223,6 @@ export type GroupMembersResponseWithAICostControl = Omit<
|
||||
> &
|
||||
Readonly<{ users: readonly GroupMemberWithAICostControl[] }>;
|
||||
|
||||
// TODO(AIGOV-473): drop once generated from codersdk.
|
||||
export type UserAISpend = Readonly<{
|
||||
user_id: string;
|
||||
spend_limit_micros: number | null;
|
||||
effective_group_id: string | null;
|
||||
limit_source: "group" | "override" | null;
|
||||
current_spend_micros: number;
|
||||
}>;
|
||||
|
||||
export function watchInboxNotifications(
|
||||
params?: WatchInboxNotificationsParams,
|
||||
): OneWayWebSocket<TypesGen.GetInboxNotificationResponse> {
|
||||
@@ -584,8 +575,8 @@ class ApiMethods {
|
||||
return response.data;
|
||||
};
|
||||
|
||||
getUserAISpend = async (): Promise<UserAISpend> => {
|
||||
const response = await this.axios.get<UserAISpend>(
|
||||
getUserAISpend = async (): Promise<TypesGen.UserAISpendStatus> => {
|
||||
const response = await this.axios.get<TypesGen.UserAISpendStatus>(
|
||||
"/api/v2/users/me/ai/spend",
|
||||
);
|
||||
return response.data;
|
||||
|
||||
@@ -4,7 +4,7 @@ import type {
|
||||
UseMutationOptions,
|
||||
UseQueryOptions,
|
||||
} from "react-query";
|
||||
import { API, type UserAISpend } from "#/api/api";
|
||||
import { API } from "#/api/api";
|
||||
import { isApiError } from "#/api/errors";
|
||||
import type {
|
||||
AuthorizationRequest,
|
||||
@@ -19,6 +19,7 @@ import type {
|
||||
UpsertUserAIBudgetOverrideRequest,
|
||||
User,
|
||||
UserAIBudgetOverride,
|
||||
UserAISpendStatus,
|
||||
UserAppearanceSettings,
|
||||
UserPreferenceSettings,
|
||||
UsersRequest,
|
||||
@@ -159,7 +160,7 @@ export const me = (metadata: MetadataState<User>) => {
|
||||
|
||||
export const meAISpendKey = [...meKey, "aiSpend"] as const;
|
||||
|
||||
export const meAISpend = (): UseQueryOptions<UserAISpend> => {
|
||||
export const meAISpend = (): UseQueryOptions<UserAISpendStatus> => {
|
||||
return {
|
||||
queryKey: meAISpendKey,
|
||||
queryFn: () => API.getUserAISpend(),
|
||||
|
||||
Reference in New Issue
Block a user