|
9 | 9 | * by the Apache License, Version 2.0 |
10 | 10 | */ |
11 | 11 |
|
| 12 | +import { create } from '@bufbuild/protobuf'; |
| 13 | +import { useQuery } from '@connectrpc/connect-query'; |
12 | 14 | import { Alert, AlertIcon, Button, DataTable, Result, Skeleton } from '@redpanda-data/ui'; |
13 | 15 | import { useNavigate, useSearch } from '@tanstack/react-router'; |
14 | 16 | import { SkipIcon } from 'components/icons'; |
15 | 17 | import { Link } from 'components/redpanda-ui/components/typography'; |
16 | | -import { useQuotasQuery } from 'hooks/use-quotas-query'; |
17 | 18 | import { useMemo } from 'react'; |
18 | 19 |
|
19 | 20 | import { |
| 21 | + ListQuotasRequestSchema, |
20 | 22 | Quota_EntityType, |
21 | 23 | type Quota_Value, |
22 | 24 | Quota_ValueType, |
23 | 25 | } from '../../../protogen/redpanda/api/dataplane/v1/quota_pb'; |
24 | | -import type { QuotaResponseSetting } from '../../../state/rest-interfaces'; |
| 26 | +import { listQuotas } from '../../../protogen/redpanda/api/dataplane/v1/quota-QuotaService_connectquery'; |
| 27 | +import { MAX_PAGE_SIZE } from '../../../react-query/react-query.utils'; |
25 | 28 | import { InfoText } from '../../../utils/tsx-utils'; |
26 | 29 | import { prettyBytes, prettyNumber } from '../../../utils/utils'; |
27 | 30 | import PageContent from '../../misc/page-content'; |
28 | 31 | import Section from '../../misc/section'; |
29 | 32 |
|
30 | 33 | /** |
31 | | - * Maps REST API quota value types to protobuf ValueType enum |
| 34 | + * Maps protobuf EntityType enum to display string |
32 | 35 | */ |
33 | | -const mapValueTypeToProto = (key: string): Quota_ValueType => { |
34 | | - switch (key) { |
35 | | - case 'producer_byte_rate': |
36 | | - return Quota_ValueType.PRODUCER_BYTE_RATE; |
37 | | - case 'consumer_byte_rate': |
38 | | - return Quota_ValueType.CONSUMER_BYTE_RATE; |
39 | | - case 'controller_mutation_rate': |
40 | | - return Quota_ValueType.CONTROLLER_MUTATION_RATE; |
41 | | - case 'request_percentage': |
42 | | - return Quota_ValueType.REQUEST_PERCENTAGE; |
43 | | - default: |
44 | | - return Quota_ValueType.UNSPECIFIED; |
45 | | - } |
46 | | -}; |
47 | | - |
48 | | -/** |
49 | | - * Maps REST API entity type to protobuf EntityType enum |
50 | | - */ |
51 | | -const mapEntityTypeToProto = (entityType: string): Quota_EntityType => { |
| 36 | +const mapEntityTypeToDisplay = (entityType: Quota_EntityType): 'client-id' | 'user' | 'ip' | 'unknown' => { |
52 | 37 | switch (entityType) { |
53 | | - case 'client-id': |
54 | | - return Quota_EntityType.CLIENT_ID; |
55 | | - case 'user': |
56 | | - return Quota_EntityType.USER; |
57 | | - case 'ip': |
58 | | - return Quota_EntityType.IP; |
| 38 | + case Quota_EntityType.CLIENT_ID: |
| 39 | + case Quota_EntityType.CLIENT_ID_PREFIX: |
| 40 | + return 'client-id'; |
| 41 | + case Quota_EntityType.USER: |
| 42 | + return 'user'; |
| 43 | + case Quota_EntityType.IP: |
| 44 | + return 'ip'; |
59 | 45 | default: |
60 | | - return Quota_EntityType.UNSPECIFIED; |
| 46 | + return 'unknown'; |
61 | 47 | } |
62 | 48 | }; |
63 | 49 |
|
| 50 | +const request = create(ListQuotasRequestSchema, { pageSize: MAX_PAGE_SIZE }); |
| 51 | + |
64 | 52 | const QuotasList = () => { |
65 | 53 | const navigate = useNavigate({ from: '/quotas' }); |
66 | 54 | const search = useSearch({ from: '/quotas' }); |
67 | | - const { data, error, isLoading } = useQuotasQuery(); |
| 55 | + const { data, error, isLoading } = useQuery(listQuotas, request); |
68 | 56 |
|
69 | 57 | const quotasData = useMemo(() => { |
70 | | - if (!data?.items) { |
| 58 | + if (!data?.quotas) { |
71 | 59 | return []; |
72 | 60 | } |
73 | 61 |
|
74 | | - return data.items.map((item) => { |
75 | | - const entityType = mapEntityTypeToProto(item.entityType); |
76 | | - const entityName = item.entityName; |
77 | | - |
78 | | - // Map entity type to display string |
79 | | - let displayType: 'client-id' | 'user' | 'ip' | 'unknown' = 'unknown'; |
80 | | - if (entityType === Quota_EntityType.CLIENT_ID) { |
81 | | - displayType = 'client-id'; |
82 | | - } else if (entityType === Quota_EntityType.USER) { |
83 | | - displayType = 'user'; |
84 | | - } else if (entityType === Quota_EntityType.IP) { |
85 | | - displayType = 'ip'; |
86 | | - } |
87 | | - |
88 | | - // Transform REST API settings to protobuf Value format |
89 | | - const values: Quota_Value[] = item.settings.map( |
90 | | - (setting: QuotaResponseSetting): Quota_Value => ({ |
91 | | - valueType: mapValueTypeToProto(setting.key), |
92 | | - value: setting.value, |
93 | | - $typeName: 'redpanda.api.dataplane.v1.Quota.Value', |
94 | | - }) |
95 | | - ); |
| 62 | + return data.quotas.map((quota) => { |
| 63 | + const entityType = quota.entity?.entityType ?? Quota_EntityType.UNSPECIFIED; |
| 64 | + const entityName = quota.entity?.entityName; |
96 | 65 |
|
97 | 66 | return { |
98 | 67 | eqKey: `${entityType}-${entityName}`, |
99 | | - entityType: displayType, |
| 68 | + entityType: mapEntityTypeToDisplay(entityType), |
100 | 69 | entityName: entityName || undefined, |
101 | | - values, |
| 70 | + values: quota.values, |
102 | 71 | }; |
103 | 72 | }); |
104 | 73 | }, [data]); |
@@ -175,19 +144,6 @@ const QuotasList = () => { |
175 | 144 | ); |
176 | 145 | } |
177 | 146 |
|
178 | | - if (data?.error) { |
179 | | - return ( |
180 | | - <PageContent> |
181 | | - <Section> |
182 | | - <Alert status="warning" style={{ marginBottom: '1em' }} variant="solid"> |
183 | | - <AlertIcon /> |
184 | | - {data.error} |
185 | | - </Alert> |
186 | | - </Section> |
187 | | - </PageContent> |
188 | | - ); |
189 | | - } |
190 | | - |
191 | 147 | return ( |
192 | 148 | <PageContent> |
193 | 149 | <Section> |
|
0 commit comments