Skip to content

Commit a6454a9

Browse files
committed
Fixes quotas page
1 parent 405bdb7 commit a6454a9

File tree

1 file changed

+99
-7
lines changed

1 file changed

+99
-7
lines changed

frontend/src/components/pages/quotas/quotas-list.tsx

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
* by the Apache License, Version 2.0
1010
*/
1111

12-
import { useQuery } from '@connectrpc/connect-query';
12+
import { createConnectQueryKey } from '@connectrpc/connect-query';
1313
import { Alert, AlertIcon, Button, DataTable, Result, Skeleton } from '@redpanda-data/ui';
14+
import { useQuery } from '@tanstack/react-query';
1415
import { SkipIcon } from 'components/icons';
16+
import { config } from 'config';
1517
import { useMemo } from 'react';
1618

1719
import {
@@ -20,22 +22,90 @@ import {
2022
Quota_ValueType,
2123
} from '../../../protogen/redpanda/api/dataplane/v1/quota_pb';
2224
import { listQuotas } from '../../../protogen/redpanda/api/dataplane/v1/quota-QuotaService_connectquery';
25+
import type { QuotaResponse, QuotaResponseSetting } from '../../../state/rest-interfaces';
2326
import { InfoText } from '../../../utils/tsx-utils';
2427
import { prettyBytes, prettyNumber } from '../../../utils/utils';
2528
import PageContent from '../../misc/page-content';
2629
import Section from '../../misc/section';
2730

31+
/**
32+
* Maps REST API quota value types to protobuf ValueType enum
33+
*/
34+
const mapValueTypeToProto = (key: string): Quota_ValueType => {
35+
switch (key) {
36+
case 'producer_byte_rate':
37+
return Quota_ValueType.PRODUCER_BYTE_RATE;
38+
case 'consumer_byte_rate':
39+
return Quota_ValueType.CONSUMER_BYTE_RATE;
40+
case 'controller_mutation_rate':
41+
return Quota_ValueType.CONTROLLER_MUTATION_RATE;
42+
case 'request_percentage':
43+
return Quota_ValueType.REQUEST_PERCENTAGE;
44+
default:
45+
return Quota_ValueType.UNSPECIFIED;
46+
}
47+
};
48+
49+
/**
50+
* Maps REST API entity type to protobuf EntityType enum
51+
*/
52+
const mapEntityTypeToProto = (entityType: string): Quota_EntityType => {
53+
switch (entityType) {
54+
case 'client-id':
55+
return Quota_EntityType.CLIENT_ID;
56+
case 'user':
57+
return Quota_EntityType.USER;
58+
case 'ip':
59+
return Quota_EntityType.IP;
60+
default:
61+
return Quota_EntityType.UNSPECIFIED;
62+
}
63+
};
64+
65+
/**
66+
* Custom hook to fetch quotas from REST API until protobuf endpoint is available
67+
*/
68+
const useQuotasQuery = () => {
69+
// Create a query key compatible with Connect Query for future migration
70+
const queryKey = createConnectQueryKey({
71+
schema: listQuotas,
72+
input: {},
73+
cardinality: 'finite',
74+
});
75+
76+
return useQuery<QuotaResponse | null>({
77+
queryKey,
78+
queryFn: async () => {
79+
const response = await config.fetch(`${config.restBasePath}/quotas`, {
80+
method: 'GET',
81+
headers: {},
82+
});
83+
84+
if (!response.ok) {
85+
if (response.status === 403 || response.status === 401) {
86+
throw new Error('You do not have permission to view quotas');
87+
}
88+
throw new Error(`Failed to fetch quotas: ${response.statusText}`);
89+
}
90+
91+
const data: QuotaResponse = await response.json();
92+
return data;
93+
},
94+
refetchOnMount: 'always',
95+
});
96+
};
97+
2898
const QuotasList = () => {
29-
const { data, error, isLoading } = useQuery(listQuotas, {});
99+
const { data, error, isLoading } = useQuotasQuery();
30100

31101
const quotasData = useMemo(() => {
32-
if (!data?.quotas) {
102+
if (!data?.items) {
33103
return [];
34104
}
35105

36-
return data.quotas.map((entry) => {
37-
const entityType = entry.entity?.entityType;
38-
const entityName = entry.entity?.entityName;
106+
return data.items.map((item) => {
107+
const entityType = mapEntityTypeToProto(item.entityType);
108+
const entityName = item.entityName;
39109

40110
// Map entity type to display string
41111
let displayType: 'client-id' | 'user' | 'ip' | 'unknown' = 'unknown';
@@ -47,11 +117,20 @@ const QuotasList = () => {
47117
displayType = 'ip';
48118
}
49119

120+
// Transform REST API settings to protobuf Value format
121+
const values: Quota_Value[] = item.settings.map(
122+
(setting: QuotaResponseSetting): Quota_Value => ({
123+
valueType: mapValueTypeToProto(setting.key),
124+
value: setting.value,
125+
$typeName: 'redpanda.api.dataplane.v1.Quota.Value',
126+
})
127+
);
128+
50129
return {
51130
eqKey: `${entityType}-${entityName}`,
52131
entityType: displayType,
53132
entityName: entityName || undefined,
54-
values: entry.values,
133+
values,
55134
};
56135
});
57136
}, [data]);
@@ -128,6 +207,19 @@ const QuotasList = () => {
128207
);
129208
}
130209

210+
if (data?.error) {
211+
return (
212+
<PageContent>
213+
<Section>
214+
<Alert status="warning" style={{ marginBottom: '1em' }} variant="solid">
215+
<AlertIcon />
216+
{data.error}
217+
</Alert>
218+
</Section>
219+
</PageContent>
220+
);
221+
}
222+
131223
return (
132224
<PageContent>
133225
<Section>

0 commit comments

Comments
 (0)