diff --git a/react/src/components/UserCredentialList.tsx b/react/src/components/UserCredentialList.tsx index 66c42b8468..2a23d012b5 100644 --- a/react/src/components/UserCredentialList.tsx +++ b/react/src/components/UserCredentialList.tsx @@ -3,6 +3,7 @@ import { filterNonNullItems, transformSorterToOrderString, } from '../helper'; +import { exportCSVWithFormattingRules } from '../helper/csv-util'; import { useUpdatableState } from '../hooks'; import { useBAIPaginationOptionState } from '../hooks/reactPaginationQueryOptions'; import BAIPropertyFilter from './BAIPropertyFilter'; @@ -29,6 +30,7 @@ import { Button, Popconfirm, Radio, + TableColumnsType, Tag, Tooltip, Typography, @@ -38,7 +40,7 @@ import graphql from 'babel-plugin-relay/macro'; import dayjs from 'dayjs'; import _ from 'lodash'; import { BanIcon, UndoIcon } from 'lucide-react'; -import { useState, useTransition } from 'react'; +import { useEffect, useState, useTransition } from 'react'; import { useTranslation } from 'react-i18next'; import { useLazyLoadQuery, useMutation } from 'react-relay'; @@ -150,6 +152,306 @@ const UserCredentialList: React.FC = () => { } `); + const columns: TableColumnsType = filterEmptyItem([ + { + key: 'user_id', + title: t('credential.UserID'), + dataIndex: 'email', + fixed: 'left', + sorter: true, + // TODO: user_id field in keypair_list is used as user's email, but sorting is done by email field + render: (value, record) => { + return record.user_id; + }, + }, + { + key: 'access_key', + title: t('credential.AccessKey'), + dataIndex: 'access_key', + sorter: true, + }, + { + key: 'is_admin', + title: t('credential.Permission'), + dataIndex: 'is_admin', + render: (isAdmin) => + isAdmin ? ( + <> + admin + user + + ) : ( + user + ), + sorter: true, + }, + { + key: 'key_age', + title: t('credential.KeyAge'), + dataIndex: 'created_at', + render: (createdAt) => { + return `${dayjs().diff(createdAt, 'day')}${t('credential.Days')}`; + }, + sorter: true, + }, + { + key: 'created_at', + title: t('credential.CreatedAt'), + dataIndex: 'created_at', + render: (createdAt) => dayjs(createdAt).format('lll'), + sorter: true, + }, + { + key: 'resource_policy', + title: t('credential.ResourcePolicy'), + dataIndex: 'resource_policy', + sorter: true, + }, + { + key: 'allocation', + title: t('credential.Allocation'), + render: (value, record) => { + return ( + + + {record.concurrency_used} + + {t('credential.Sessions')} + + + + {record.rate_limit} + + {t('credential.ReqPer15Min')} + + + + {record.num_queries} + + {t('credential.Queries')} + + + + ); + }, + }, + { + key: 'control', + title: t('general.Control'), + fixed: 'right', + render: (value, record) => { + return ( + +