import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import * as XLSX from 'xlsx'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { createColumnHelper, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table'; import { LucideDownload, LucidePlus, LucideSearch, LucideTrash2, LucideUpload, LucideUserPen, } from 'lucide-react'; import Spotlight from '@/components/spotlight'; import { TableEmpty } from '@/components/table-skeleton'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardFooter, CardHeader, CardTitle, } from '@/components/ui/card'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { SearchInput } from '@/components/ui/input'; import { RAGFlowPagination } from '@/components/ui/ragflow-pagination'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { createWhitelistEntry, deleteWhitelistEntry, importWhitelistFromExcel, listWhitelist, updateWhitelistEntry, } from '@/services/admin-service'; import { EMPTY_DATA, createFuzzySearchFn, getSortIcon } from './utils'; import dayjs from 'dayjs'; import useCreateEmailForm from './forms/email-form'; import useImportExcelForm, { ImportExcelFormData, } from './forms/import-excel-form'; const columnHelper = createColumnHelper(); const globalFilterFn = createFuzzySearchFn([ 'email', ]); function AdminWhitelist() { const { t } = useTranslation(); const queryClient = useQueryClient(); const createEmailForm = useCreateEmailForm(); const editEmailForm = useCreateEmailForm(); const importExcelForm = useImportExcelForm(); const [itemToMakeAction, setItemToMakeAction] = useState(null); const [deleteModalOpen, setDeleteModalOpen] = useState(false); const [createModalOpen, setCreateModalOpen] = useState(false); const [editModalOpen, setEditModalOpen] = useState(false); const [importModalOpen, setImportModalOpen] = useState(false); const { data: whitelist } = useQuery({ queryKey: ['admin/listWhitelist'], queryFn: async () => (await listWhitelist())?.data?.data?.white_list, retry: false, }); // Reset form when editing a different email useEffect(() => { if (itemToMakeAction && editModalOpen) { editEmailForm.form.setValue('email', itemToMakeAction.email); } }, [itemToMakeAction, editModalOpen, editEmailForm.form]); const createWhitelistEntryMutation = useMutation({ mutationFn: (data: { email: string }) => createWhitelistEntry(data.email), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listWhitelist'] }); setCreateModalOpen(false); createEmailForm.form.reset(); }, onError: (error) => { console.error('Error creating email:', error); }, retry: false, }); const updateWhitelistEntryMutation = useMutation({ mutationFn: (data: { id: number; email: string }) => updateWhitelistEntry(data.id, data.email), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listWhitelist'] }); setEditModalOpen(false); setItemToMakeAction(null); editEmailForm.form.reset(); }, }); const deleteWhitelistEntryMutation = useMutation({ mutationFn: (data: { email: string }) => deleteWhitelistEntry(data.email), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listWhitelist'] }); setDeleteModalOpen(false); setItemToMakeAction(null); }, onError: (error) => { console.error('Error deleting email:', error); }, }); const importExcelMutation = useMutation({ mutationFn: (data: ImportExcelFormData) => importWhitelistFromExcel(data.file), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listWhitelist'] }); setImportModalOpen(false); importExcelForm.form.reset(); }, onError: (error) => { console.error('Error importing Excel:', error); }, retry: false, }); const handleExportExcel = () => { const columnData = (whitelist ?? EMPTY_DATA).map((item) => ({ email: item.email, })); const worksheet = XLSX.utils.json_to_sheet(columnData); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); XLSX.writeFile( workbook, `whitelist_${dayjs(new Date()).format('YYYYMMDDHHmmss')}.xlsx`, ); }; const columnDefs = useMemo( () => [ columnHelper.accessor('email', { header: t('admin.email'), enableSorting: false, }), columnHelper.accessor('create_date', { header: t('admin.createDate'), }), columnHelper.accessor('update_date', { header: t('admin.updateDate'), }), columnHelper.display({ id: 'actions', header: t('admin.actions'), cell: ({ row }) => (
), }), ], [t], ); const table = useReactTable({ data: whitelist ?? EMPTY_DATA, columns: columnDefs, globalFilterFn, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), getPaginationRowModel: getPaginationRowModel(), enableSorting: false, }); return ( <> {t('admin.whitelistManagement')}
table.setGlobalFilter(e.target.value)} prefix={} />
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : header.column.getCanSort() ? ( ) : ( flexRender( header.column.columnDef.header, header.getContext(), ) )} ))} ))} {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} )) ) : ( )}
{ table.setPagination({ pageIndex: page - 1, pageSize, }); }} />
{/* Delete Confirmation Modal */} { if (!deleteModalOpen) { setItemToMakeAction(null); } }} > {t('admin.deleteEmail')}
{t('admin.deleteWhitelistEmailConfirmation')}
{itemToMakeAction?.email}
{/* Create Email Modal */} { if (!createModalOpen) { createEmailForm.form.reset(); } }} > {t('admin.createEmail')}
{/* Edit Email Modal */} { if (!editModalOpen) { setItemToMakeAction(null); editEmailForm.form.reset(); } }} > {t('admin.editEmail')}
{ if (itemToMakeAction) { updateWhitelistEntryMutation.mutate({ id: itemToMakeAction.id, email: value.email, }); } }} />
{/* Import Excel Modal */} { if (!importModalOpen) { importExcelForm.form.reset(); } }} > {t('admin.importWhitelist')}
); } export default AdminWhitelist;