import { mapKeys } from 'lodash'; import { useId, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import Spotlight from '@/components/spotlight'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Switch } from '@/components/ui/switch'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { LucideEdit3, LucideTrash2, LucideUserPlus } from 'lucide-react'; import { assignRolePermissions, createRole, deleteRole, listResources, listRolesWithPermission, revokeRolePermissions, updateRoleDescription, } from '@/services/admin-service'; import Empty from '@/components/empty/empty'; import useCreateRoleForm, { CreateRoleFormData } from './forms/role-form'; import { PERMISSION_TYPES } from './utils'; function AdminRoles() { const { t } = useTranslation(); const queryClient = useQueryClient(); const createRoleForm = useCreateRoleForm(); const [isAddRoleModalOpen, setAddRoleModalOpen] = useState(false); const editRoleDescriptionFormId = useId(); const [isEditRoleDescriptionModalOpen, setEditRoleDescriptionModalOpen] = useState(false); const [roleDescription, setRoleDescription] = useState(''); const [deleteModalOpen, setDeleteModalOpen] = useState(false); const [roleToMakeAction, setRoleToMakeAction] = useState(null); const { data: roleList } = useQuery({ queryKey: ['admin/listRolesWithPermission'], queryFn: async () => (await listRolesWithPermission())?.data?.data?.roles, retry: false, }); const { data: resourceTypes } = useQuery({ queryKey: ['admin/resourceTypes'], queryFn: async () => (await listResources()).data.data.resource_types, retry: false, }); const updateRoleDescriptionMutation = useMutation({ mutationFn: (data: { name: string; description: string }) => updateRoleDescription(data.name, data.description), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listRolesWithPermission'], }); setEditRoleDescriptionModalOpen(false); setRoleToMakeAction(null); }, retry: false, }); const updateRolePermissionsMutation = useMutation({ mutationFn: (data: { name: string; resourceName: string; permissionType: (typeof PERMISSION_TYPES)[number]; value: boolean; }) => { const permissionDiffData = { [data.resourceName.toLowerCase()]: { [data.permissionType]: data.value, }, }; return data.value ? assignRolePermissions(data.name, permissionDiffData) : revokeRolePermissions(data.name, permissionDiffData); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listRolesWithPermission'], }); }, retry: false, }); const createRoleMutation = useMutation({ mutationFn: async (data: CreateRoleFormData) => { const { data: { data: createdRoleDetail } = {} } = await createRole({ roleName: data.name, description: data.description, }); if (!createdRoleDetail) { throw new Error(); } await assignRolePermissions( data.name, mapKeys(data.permissions, (_, key) => key.toLowerCase()), ); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listRolesWithPermission'], }); createRoleForm.form.reset(); setAddRoleModalOpen(false); }, retry: false, }); const deleteRoleMutation = useMutation({ mutationFn: (roleName: string) => deleteRole(roleName), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin/listRolesWithPermission'], }); setDeleteModalOpen(false); setRoleToMakeAction(null); }, retry: false, }); return ( <> {t('admin.roles')} {roleList?.length ? ( roleList.map((role) => (
{role.role_name}
{role.description || ( {t('admin.noDescription')} )}
{resourceTypes?.map((resourceName) => ( {t( `admin.resourceType.${resourceName.toLowerCase()}`, )} ))} {resourceTypes?.map((resourceName) => { const permission = role.permissions[resourceName.toLowerCase()]; return ( {PERMISSION_TYPES.map((permissionType) => ( ))} ); })}
)) ) : ( )}
{/* Add role modal */} { if (!isAddRoleModalOpen) { createRoleForm.form.reset(); } }} > {t('admin.addNewRole')}
{/* Modify role description modal */} { if (!isEditRoleDescriptionModalOpen) { setRoleToMakeAction(null); } }} > {t('admin.editRoleDescription')}
{ evt.preventDefault(); updateRoleDescriptionMutation.mutate({ name: roleToMakeAction!?.role_name, description: roleDescription.trim(), }); }} >
{/* Delete role modal */} { if (!deleteModalOpen) { setRoleToMakeAction(null); } }} > {t('admin.deleteRole')}
{t('admin.deleteRoleConfirmation')}
{roleToMakeAction?.role_name}
); } export default AdminRoles;